/*
 * Created on Jan 9, 2005
 */
package org.scohen.juploadr.upload;

import java.util.LinkedList;

import org.scohen.juploadr.app.UploadImage;
import org.scohen.juploadr.event.UploadCompleteEvent;
import org.scohen.juploadr.event.UploadEvent;
import org.scohen.juploadr.event.UploadStatusMonitor;
import org.scohen.juploadr.uploadapi.CommunicationException;
import org.scohen.juploadr.uploadapi.ImageUploadApi;
import org.scohen.juploadr.uploadapi.ProtocolException;
import org.scohen.juploadr.uploadapi.UploadFailedException;

/**
 * @author John
 */
public class UploaderThread extends Thread {
    private LinkedList uploadQueue;
    private UploadStatusMonitor monitor;
    private boolean uploadComplete = false;
    private boolean cancelled = false;

    public UploaderThread(LinkedList uploadQueue, UploadStatusMonitor monitor) {
        this.uploadQueue = uploadQueue;
        setMonitor(monitor);
    }

    private void verifyMonitor(UploadStatusMonitor monitor) {
        if (monitor == null) {
            monitor = new UploadStatusMonitor() {

                public void uploadStarted(UploadEvent e) {
                    System.out.println("UploadStarted " + e);
                }

                public void uploadStatusChanged(UploadEvent e) {
                    System.out.println("UploadStatusChanged " + e);
                }

                public void uploadFinished(UploadCompleteEvent e) {
                    System.out.println("UploadFinished " + e);
                }

                public void allUploadsComplete() {
                    System.out.println("AllUploadsComplete");
                }

                public void uploadCancelled() {
                    System.out.println("Upload cancelled");
                }

                public void uploadFailed(UploadEvent e) {
                    System.out.println("UploadFailed " + e);
                }
            };
        }
    }

    public void run() {
        while (true) {
            uploadComplete = false;
            UploadImage imageAttributes = null;
            synchronized (uploadQueue) {
                if (uploadQueue.size() > 0 && !cancelled) {
                    // Grab and remove the next item off the queue.
                    imageAttributes = (UploadImage) uploadQueue.removeFirst();
                    if (uploadQueue.size() == 0) {
                        uploadComplete = true;
                    }
                } else {
                    // if it was cancelled, send an alert
                    if (cancelled) {
                        uploadQueue.clear();
                        monitor.uploadCancelled();
                    }
                    imageAttributes = null;
                    // Wait for notification that there's something to grab.
                    try {
                        uploadQueue.wait();
                    } catch (InterruptedException e) {
                        // TODO: handle exception
                        e.printStackTrace();
                    }
                }
                // Release the queue's monitor before doing the slow work.
            }
            if (imageAttributes != null) {
                ImageUploadApi api = ImageUploadApi.getInstance();
                try {
                    // Upload the image!
                    if (!api.isCurrentAccountAuthenticated()) {
                        api.authenticateCurrentAccount();
                    }
                    api.upload(imageAttributes, monitor);

                } catch (UploadFailedException e) {
                    e.printStackTrace();
                    monitor.uploadFailed(new UploadEvent(imageAttributes, 0,
                            true, false, e.getMessage()));
                } catch (CommunicationException e) {
                    monitor.uploadFailed(new UploadEvent(imageAttributes, 0,
                            true, false, e.getMessage()));
                    e.printStackTrace();
                } catch (ProtocolException e) {
                    monitor.uploadFailed(new UploadEvent(imageAttributes, 0,
                            false, false, e.getMessage()));
                    e.printStackTrace();
                }
            }

            if (uploadComplete) {
                monitor.allUploadsComplete();
            }
        }
    }

    /**
     * @return Returns the monitor.
     */
    public UploadStatusMonitor getMonitor() {
        return monitor;
    }

    /**
     * @param monitor
     *            The monitor to set.
     */
    public void setMonitor(UploadStatusMonitor monitor) {

        MultiMonitorFacade multiMonitor = new MultiMonitorFacade();
        multiMonitor.addMonitor(monitor);
        verifyMonitor(monitor);
        this.monitor = multiMonitor;
    }

    /**
     * @return Returns the cancelled.
     */
    public boolean isCancelled() {
        return cancelled;
    }

    /**
     * @param cancelled
     *            The cancelled to set.
     */
    public void setCancelled(boolean cancelled) {
        this.cancelled = cancelled;
    }

}